package com.zx1316.javadoudizhuserver;

import javafx.application.Platform;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

//这个类处理服务端对客户端的连接
public class ServerThread extends Thread {
    private final Controller CONTROLLER;
    private final GameThread GAME_THREAD;
    private final ServerSocket SERVER_SOCKET;
    private final Server SERVER;
    private final Object LOCK;
    private final String PASSWORD;

    public ServerThread(Server server, ServerSocket serverSocket, String password, Object lock, GameThread gameThread, Controller controller) {
        this.CONTROLLER = controller;
        this.SERVER = server;
        this.SERVER_SOCKET = serverSocket;
        this.LOCK = lock;
        this.PASSWORD = password;
        this.GAME_THREAD = gameThread;
    }

    @Override
    public void run() {
        Socket socket;
        while (true) {
            try {
                socket = SERVER_SOCKET.accept();
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
            try {
                BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter w = new PrintWriter(socket.getOutputStream());
                String message = r.readLine();
                String[] str = message.split("@");
                if (str.length == 1 && !PASSWORD.equals("") || str.length != 1 && !str[1].equals(PASSWORD)) {
                    sendMessage(w, "WRONG");
                    socket.close();
                } else if (Server.getClients()[0] != null && Server.getClients()[1] != null && Server.getClients()[2] != null) {
                    sendMessage(w, "MAX");
                    socket.close();
                } else {
                    String name = str[0];
                    boolean flag = true;
                    int pos = 0;
                    if (!GAME_THREAD.isInGame()) {
                        for (int i = 0; i < 3; i++) {
                            if (Server.getClients()[i] != null && Server.getClients()[i].getPlayerName().equals(name)) {
                                sendMessage(w, "SAME");
                                socket.close();
                                flag = false;
                                break;
                            }
                        }
                        if (flag) {
                            while (Server.getClients()[pos] != null) {
                                pos++;
                            }
                        }
                    } else {
                        for (pos = 0; pos < 3; pos++) {
                            if (GAME_THREAD.getPlayerList()[pos].equals(name)) {
                                break;
                            }
                        }
                        if (pos == 3) {
                            w.println("MAX");
                            w.flush();
                            socket.close();
                            flag = false;
                        }
                    }
                    if (flag) {
                        ClientThread client = new ClientThread(socket, name, LOCK, GAME_THREAD, CONTROLLER);
                        Server.getClients()[pos] = client;
                        client.start();
                        sendMessage(w, "RULES@" + SERVER.getTotalRounds() + "@" + SERVER.isHasTips() + "@" + SERVER.isAllowDouble());
                        StringBuilder sb = new StringBuilder("NAME");
                        if (!GAME_THREAD.isInGame()) {
                            for (int i = 0; i < 3; i++) {
                                sb.append("@");
                                if (Server.getClients()[i] != null) {
                                    sb.append(Server.getClients()[i].getPlayerName());
                                } else {
                                    sb.append(" ");
                                }
                            }
                            for (int i = 0; i < 3; i++) {
                                sendMessage(sb.toString(), i);
                            }
                            int finalPos = pos;
                            Platform.runLater(() -> {
                                String name1 = Server.getClients()[finalPos].getPlayerName();
                                switch (finalPos) {
                                    case 0 -> CONTROLLER.name1.setText(name1);
                                    case 1 -> CONTROLLER.name2.setText(name1);
                                    default -> CONTROLLER.name3.setText(name1);
                                }
                            });
                        } else {
                            for (int i = 0; i < 3; i++) {
                                sb.append("@");
                                sb.append(GAME_THREAD.getPlayerList()[i]);
                            }
                            sendMessage(w, sb.toString());
                            for (int i = 0; i < 3; i++) {
                                if (!client.equals(Server.getClients()[i])) {
                                    sendMessage("ADD@" + name, i);
                                }
                                if (Server.getClients()[i] == null) {
                                    sendMessage(w, "DELETE@" + GAME_THREAD.getPlayerList()[i]);
                                }
                            }
                        }
                        for (int i = 0; i < 3; i++) {
                            if (Server.getClients()[i] != null && Server.getClients()[i].isReady()) {
                                sendMessage(w, "READY@" + Server.getClients()[i].getPlayerName());
                            }
                        }
                        if (GAME_THREAD.isInGame()) {
                            sendMessage(w, "SCORE@" + GAME_THREAD.getScores()[0] + "@" + GAME_THREAD.getScores()[1] + "@" + GAME_THREAD.getScores()[2] + "@" + GAME_THREAD.getRounds());
                            for (String send : GAME_THREAD.getRecords().get(pos)) {
                                sendMessage(w, send);
                            }
                            if (GAME_THREAD.isPause() && pos == GAME_THREAD.getWaitingFor()) {
                                synchronized (LOCK) {
                                    LOCK.notify();
                                }
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void sendMessage(PrintWriter w, String message) {
        w.println(message);
        w.flush();
    }

    public void sendMessage(String message, int id) {
        if (Server.getClients()[id] != null) {
            Server.getClients()[id].getWriter().println(message);
            Server.getClients()[id].getWriter().flush();
        }
    }

    public ServerSocket getServerSocket() {
        return SERVER_SOCKET;
    }
}
